import { cadAppLog, DocumentObject, IdObj, PickType, Types } from '@amcax/base';
import { ctx2, dataManager, docMgr, referenceManager } from '@app-cad/module';
import { Renderer3D, RendererMgr } from '@amcax/renderer';
import { cmdMgr } from './CmdManager';

class ReferenceRenderManager {
  referenceObjects: DocumentObject[] = [];
  private renderer: Renderer3D;

  // 渲染基本的基准面

  init() {
    this.renderer = RendererMgr.getRender<Renderer3D>('3d');
  }

  // 三个基本面是前端自行补充，后端文档中实际不存在
  renderBasePlanes() {
    cadAppLog('[debug]renderBasePlanes...');
    if (this.renderer == null) {
      return;
    }
    const startColorId = this.renderer.renderBaseReferencePlane();

    const originPointObj: IdObj = {
      i: 0,
      t: PickType.VERTEX,
      o: 'ORIGIN',
    };
    dataManager.addToColorMap(startColorId, originPointObj);

    referenceManager.basicReferencePlaneIDs.forEach((id, planeIndex) => {
      for (let i = 0; i < 5; i++) {
        const colorId = startColorId + i + planeIndex * 5 + 1;

        const idObj: IdObj =
          i === 0
            ? {
                i: 0,
                t: PickType.PLANE,
                o: id,
              }
            : {
                i: i - 1,
                t: PickType.LINE,
                o: id,
              };

        dataManager.addToColorMap(colorId, idObj);
      }
    });
  }

  // 渲染参考类型的object
  async renderReferenceObjects(dxids?: string[]) {
    if (this.renderer == null) {
      return;
    }

    const updateTargets = docMgr.flatDocumentObjects.filter(
      (o) =>
        (dxids == null || dxids.includes(o.dxid)) &&
        referenceManager.getObjectById(o.dxid) == null,
    );

    // 若某元素被隐藏，则初始化获取visualData时该元素会被略过
    // 因此参考的依赖元素可能没有visualData，需要按需获取
    const referenceRenderDependency = [];

    updateTargets.forEach((o) => {
      if (o.type === Types.FRAME && typeof o?.params?.origin === 'string') {
        referenceRenderDependency.push(o.params.origin);
      }
    });

    await cmdMgr.fetchDependentShapeInfo(referenceRenderDependency);

    updateTargets.forEach((o) => {
      this.renderer.renderReferenceObject({ ...o, children: [] }, o.dxid);
    });
  }

  removeReferenceObjects(dxids: string[]) {
    if (this.renderer == null) {
      return;
    }

    referenceManager.removeObjects(dxids);
  }

  setVisibility(dxid: string, visibility: boolean) {
    const targetReference = referenceManager.getObjectById(dxid);

    if (visibility) {
      targetReference?.show();
    } else {
      targetReference?.hide();
    }
    ctx2.viewer.requestRender();
  }
}

export const referenceRenderManager = new ReferenceRenderManager();
